package com.example.a_java.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 数据库初始化工具类
 * 在应用启动时自动执行SQL脚本初始化数据库
 */
@Component
@Slf4j
public class DatabaseInitializer implements CommandLineRunner {

    @Autowired
    private DataSource dataSource;

    @Override
    public void run(String... args) {
        try {
            // // 1. 创建表结构
            // executeScript("db/repayment_tables.sql");
            // log.info("成功初始化还款和逾期相关表结构");

            // // 2. 插入示例数据
            // executeScript("db/repayment_sample_data.sql");
            // log.info("成功插入还款和逾期相关示例数据");
        } catch (Exception e) {
            log.error("初始化数据库时发生错误", e);
        }
    }

    /**
     * 执行SQL脚本
     * @param scriptPath 脚本路径
     */
    private void executeScript(String scriptPath) {
        ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
        populator.addScript(new ClassPathResource(scriptPath));
        populator.execute(dataSource);
    }

    /**
     * 手动执行SQL脚本（备用方法，当ResourceDatabasePopulator不适用时）
     * @param scriptPath 脚本路径
     */
    private void executeSqlScript(String scriptPath) {
        try (Connection connection = dataSource.getConnection()) {
            ScriptRunner scriptRunner = new ScriptRunner(connection, false, true);
            ClassPathResource resource = new ClassPathResource(scriptPath);
            InputStreamReader reader = new InputStreamReader(resource.getInputStream());
            scriptRunner.runScript(reader);
        } catch (SQLException | IOException e) {
            log.error("执行SQL脚本时发生错误: " + scriptPath, e);
            throw new RuntimeException("执行SQL脚本失败", e);
        }
    }

    /**
     * 简化版脚本执行器
     */
    private static class ScriptRunner {
        private final Connection connection;
        private final boolean autoCommit;
        private final boolean stopOnError;
        private String delimiter = ";";

        public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError) {
            this.connection = connection;
            this.autoCommit = autoCommit;
            this.stopOnError = stopOnError;
            try {
                connection.setAutoCommit(autoCommit);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

        public void runScript(InputStreamReader reader) {
            try (BufferedReader lineReader = new BufferedReader(reader)) {
                StringBuilder command = new StringBuilder();
                String line;
                while ((line = lineReader.readLine()) != null) {
                    line = line.trim();
                    if (line.isEmpty() || line.startsWith("--")) {
                        continue;
                    }

                    command.append(line);

                    if (line.endsWith(delimiter)) {
                        executeCommand(command.toString());
                        command = new StringBuilder();
                    } else {
                        command.append(" ");
                    }
                }
                if (command.length() > 0) {
                    executeCommand(command.toString());
                }
                if (!autoCommit) {
                    connection.commit();
                }
            } catch (Exception e) {
                throw new RuntimeException("运行SQL脚本错误", e);
            }
        }

        private void executeCommand(String command) {
            if (command.trim().isEmpty()) {
                return;
            }
            try (Statement statement = connection.createStatement()) {
                statement.execute(command);
            } catch (SQLException e) {
                if (stopOnError) {
                    throw new RuntimeException("执行SQL命令错误: " + command, e);
                } else {
                    log.error("执行SQL命令错误: " + command, e);
                }
            }
        }
    }
} 